//整体结构：创建子进程，由子进程获取指令，父进程判断完成的怎么样
//1.打印标识开头
//2.获取指令字符串
//3.分析字符串提取指令到grev[]
//4.部分指令的特殊处理，例如cd
//5.替换进程execvpe
//////////////////////////////////////////////////////////////////
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>

#define SIZE 1024
#define NUM 32

#define EMPTY 0
#define INPUTDIR 1
#define OUTPUTDIR 2
#define APPPUTDIR 3

int status_dir;

char str[SIZE];
char* _grev[NUM];
char _env[NUM][NUM];

char* getfile(char* str, int end)
{
    while(str[end] != ' ')
    {
        if(str[end] == '>')
        {
            if(str[end - 1] == '>')
            {
                status_dir = APPPUTDIR;
                str[end-1] = '\0';
                return &str[end+1];
            }
            status_dir = OUTPUTDIR;
            str[end] = '\0';
            return &str[end+1];
        }
        else if(str[end] == '<')
        {
            status_dir = INPUTDIR;
            str[end] = '\0';
            return &str[end+1];
        }
        else{
            end--;
        }
    }
    return NULL;
}

int main()
{
    int num_env = 0;
    status_dir = EMPTY;
    while(1)
    {
            //1.
            printf("[root$loadhost myshell]# ");
            fflush(stdout);
            //2.
            memset(str,SIZE,'\0');
            fgets(str, SIZE, stdin);
            int sz = strlen(str);
            str[sz - 1] = '\0';
            //3.
            int end = sz - 2;
            char* file_end = getfile(str, end);
            
            _grev[0] = strtok(str, " ");
            int index = 1;
            //4.
            if(strcmp(_grev[0],"ls") == 0)
            {
                _grev[index++] = (char*)"--color=auto";
            }
            if(strcmp(_grev[0], "ll") == 0)
            {
                _grev[0] = (char*)"ls";
                _grev[index++] = (char*)"--color=auto";
                _grev[index++] = (char*)"-l";
            }
            
            while(_grev[index++] = strtok(NULL, " "));
            if(strcmp(_grev[0], "cd") == 0)
            {
                if(_grev[1]) chdir(_grev[1]);
                continue;
            }
            if(strcmp(_grev[0], "export") == 0 && _grev[1])
            {
                memcpy(_env[num_env],_grev[1],strlen(_grev[1])+1);
                putenv(_env[num_env]);
                num_env++;
                continue;
            }
        pid_t id = fork();
        if(id < 0)
        {
            perror("fork");
            exit(1);
        }
        else if(id == 0)
        {
            //child
            //5
            int fd;
            switch (status_dir)
            {
                case INPUTDIR:
                    fd = open(file_end, O_RDONLY);
                    dup2(fd,0);
                    break;
                case OUTPUTDIR:
                    fd = open(file_end, O_WRONLY | O_CREAT | O_TRUNC, 0666);
                    dup2(fd,1);
                    break;
                case APPPUTDIR:
                    fd = open(file_end, O_WRONLY | O_CREAT | O_APPEND, 0666);
                    dup2(fd,1);
                    break;
                case EMPTY:
                    break;
                default:
                    printf("bug?\n");
                    break;
            }

            
            execvp(_grev[0], _grev);
            exit(2);
        }
        else {
            //father
            int status = 0;
            pid_t ret = waitpid(id, &status, 0);
            if(ret < 0)
            {
                printf("等待子进程失败\n");
                exit(2);
            }
            else{
                if(WIFEXITED(status))
                {
                    printf("子进程退出码：%d\n",WEXITSTATUS(status));
                }
                else if(WIFSIGNALED(status))
                {
                    printf("子进程终止信号：%d\n",WTERMSIG(status));
                }
            }
        }
    }
    return 0;
}
